﻿using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Windows;
using System.Windows.Data;
using System.Windows.Media;
using System.Linq;
using System.Reflection;

namespace Gmantis.Controls.Chart
{
    public static class Extensions
    {
        // Fields
        internal static Rect EmptyRect = Rect.Empty;

        // Methods
        internal static Binding From<T>(this Binding binding, Expression<Func<T, object>> expr)
        {
            binding.Path = new PropertyPath(GetPropertyPath<T>(expr), new object[0]);
            return binding;
        }

        internal static Binding From<T>(this Binding binding, T source, Expression<Func<T, object>> expr)
        {
            binding.Source = source;
            binding.Path = new PropertyPath(GetPropertyPath<T>(expr), new object[0]);
            return binding;
        }

        public static DateTime FromOADate(this double d)
        {
            return DateTime.FromOADate(d);
        }

        internal static string GetPropertyPath<T>(Expression<Func<T, object>> expression)
        {
            MemberExpression expression3;
            IList<string> source = new List<string>();
            for (System.Linq.Expressions.Expression expression2 = expression.Body; expression2.NodeType != ExpressionType.Parameter; expression2 = expression3.Expression)
            {
                ExpressionType nodeType = expression2.NodeType;
                if (nodeType == ExpressionType.Call)
                {
                    MethodCallExpression expression4 = (MethodCallExpression)expression2;
                    throw new InvalidOperationException("The member '" + expression4.Method.Name + "' is a method call but a Property or Field was expected.");
                }
                if ((nodeType != ExpressionType.Convert) && (nodeType != ExpressionType.MemberAccess))
                {
                    throw new InvalidOperationException("The expression NodeType '" + expression2.NodeType.ToString() + "' is not supported, expected MemberAccess, Convert, or Call.");
                }
                expression3 = (expression2.NodeType == ExpressionType.MemberAccess) ? ((MemberExpression)expression2) : ((MemberExpression)((UnaryExpression)expression2).Operand);
                if ((expression3.Member.MemberType != MemberTypes.Property) && (expression3.Member.MemberType != MemberTypes.Field))
                {
                    throw new InvalidOperationException("The member '" + expression3.Member.Name + "' is a " + expression3.Member.MemberType.ToString() + " but a Property or Field is expected.");
                }
                source.Add(expression3.Member.Name);
            }
            return string.Join(".", source.Reverse<string>().ToArray<string>());
        }

        internal static Rect IntersectRect(this Rect rect1, Rect rect2)
        {
            rect1.Intersect(rect2);
            return rect1;
        }

        private static bool IntersectsWith(Rect rect1, Rect rect2)
        {
            return ((((!rect1.IsEmptyRect() && !rect2.IsEmptyRect()) && ((rect2.Left <= rect1.Right) && (rect2.Right >= rect1.Left))) && (rect2.Top <= rect1.Bottom)) && (rect2.Bottom >= rect1.Top));
        }

        internal static bool IsEmptyRect(this Rect rect)
        {
            return rect.IsEmpty;
        }

        internal static bool IsInVisualTree(this DependencyObject element)
        {
            return IsInVisualTree(element, Application.Current.RootVisual);
        }

        private static bool IsInVisualTree(DependencyObject element, DependencyObject ancestor)
        {
            for (DependencyObject obj2 = element; obj2 != null; obj2 = VisualTreeHelper.GetParent(obj2))
            {
                if (obj2 == ancestor)
                {
                    return true;
                }
            }
            return false;
        }

        internal static DoubleCollection ToCollection(this double[] thisPointArray)
        {
            DoubleCollection doubles = new DoubleCollection();
            for (int i = 0; i < thisPointArray.Length; i++)
            {
                doubles.Add(thisPointArray[i]);
            }
            return doubles;
        }

        internal static PointCollection ToCollection(this Point[] thisPointArray)
        {
            PointCollection points = new PointCollection();
            int length = thisPointArray.Length;
            for (int i = 0; i < length; i++)
            {
                points.Add(thisPointArray[i]);
            }
            return points;
        }
    }
}
